using System;
using System.IO;
using System.Text;
using System.Web;

using ICSharpCode.SharpZipLib.Zip;

using Krystalware.SlickUpload;
using Krystalware.SlickUpload.Configuration;
using Krystalware.SlickUpload.Storage;

namespace AspNetMvc3Cs.Storage
{
    public class ZipUploadStreamProvider : UploadStreamProviderBase
    {
        string _location;

        public ZipUploadStreamProvider(UploadStreamProviderElement settings)
            : base(settings)
		{
            _location = settings.Parameters["location"];

            if (string.IsNullOrEmpty(_location))
                _location = "~/Files/";        
        }

        public override Stream GetReadStream(UploadedFile file)
        {
            FileStream fileS = null;
            ZipInputStream zipS = null;

            try
            {
                fileS = File.OpenRead(file.ServerLocation);
                zipS = new ZipInputStream(fileS);

                zipS.GetNextEntry();

                return zipS;
            }
            catch
            {
                if (zipS != null)
                    zipS.Dispose();
                if (fileS != null)
                    fileS.Dispose();

                throw;
            } 
        }

        public override Stream GetWriteStream(UploadedFile file)
        {
            file.ServerLocation = Path.Combine(HttpContext.Current.Server.MapPath(_location), Path.GetFileNameWithoutExtension(GetValidFileName(file.ClientName)) + ".zip");

            Directory.CreateDirectory(Path.GetDirectoryName(file.ServerLocation));

            FileStream fileS = null;
            ZipOutputStream zipS = null;

            try
            {
                fileS = File.OpenWrite(file.ServerLocation);
                zipS = new ZipOutputStream(fileS);

                zipS.SetLevel(5);

                zipS.PutNextEntry(new ZipEntry(file.ClientName));

                return zipS;
            }
            catch
            {
                if (zipS != null)
                    zipS.Dispose();
                if (fileS != null)
                    fileS.Dispose();

                throw;
            }
        }

        public override void RemoveOutput(UploadedFile file)
        {
            if (File.Exists(file.ServerLocation))
                File.Delete(file.ServerLocation);
        }

        string GetValidFileName(string fileName)
        {
            StringBuilder validFileName = new StringBuilder(fileName);

            foreach (char invalidChar in Path.GetInvalidFileNameChars())
                validFileName.Replace(invalidChar, '-');

            return validFileName.ToString();
        }
    }
}